package com.yxinsur.imc.business.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yxinsur.imc.business.domain.ImcFundOrderExpression;
import com.yxinsur.imc.business.domain.ImcFundOrderVariable;
import com.yxinsur.imc.business.enums.ExpenseExpressionMsgTypeEnum;
import com.yxinsur.imc.business.enums.FundMonthlyStrategyEnum;
import com.yxinsur.imc.business.enums.IsDeletedEnum;
import com.yxinsur.imc.business.form.FundOrderExpressionForm;
import com.yxinsur.imc.business.form.FundOrderForm;
import com.yxinsur.imc.business.mapper.ImcFundOrderExpressionMapper;
import com.yxinsur.imc.business.mapper.ImcFundOrderVariableMapper;
import com.yxinsur.imc.business.mapper.ImcOrderRiskMapper;
import com.yxinsur.imc.business.service.IImcFundOrderExpressionService;
import com.yxinsur.imc.business.vo.ContractExpenseExpressionMessageVo;
import com.yxinsur.imc.business.vo.FundOrderExpressionVo;
import com.yxinsur.imc.common.core.domain.AjaxResult;
import com.yxinsur.imc.common.exception.BusinessException;
import com.yxinsur.imc.common.utils.DateUtils;
import com.yxinsur.imc.common.utils.SecurityUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 保单口径（暨口径达式配置）Service业务层处理
 *
 * @author imc
 * @date 2021-10-29
 */
@Service
@Slf4j
public class ImcFundOrderExpressionServiceImpl extends ServiceImpl<ImcFundOrderExpressionMapper, ImcFundOrderExpression> implements IImcFundOrderExpressionService {
    @Autowired
    private ImcFundOrderExpressionMapper imcFundOrderExpressionMapper;

    @Autowired
    private ImcRecnExpenseServiceImpl recnExpenseService;

    @Autowired
    private ImcOrderRiskMapper orderRiskMapper;

    @Autowired
    private ImcFundOrderVariableMapper fundOrderVariableMapper;

    /**
     * 查询保单口径（暨口径达式配置）
     *
     * @param id 保单口径（暨口径达式配置）ID
     * @return 保单口径（暨口径达式配置）
     */
    @Override
    public ImcFundOrderExpression selectImcFundOrderExpressionById(String id) {
        return imcFundOrderExpressionMapper.selectImcFundOrderExpressionById(id);
    }

    /**
     * 查询保单口径（暨口径达式配置）列表
     *
     * @param imcFundOrderExpression 保单口径（暨口径达式配置）
     * @return 保单口径（暨口径达式配置）
     */
    @Override
    public List<ImcFundOrderExpression> selectImcFundOrderExpressionList(ImcFundOrderExpression imcFundOrderExpression) {
        return imcFundOrderExpressionMapper.selectImcFundOrderExpressionList(imcFundOrderExpression);
    }

    /**
     * 新增保单口径（暨口径达式配置）
     *
     * @param fundOrderForm 保单口径（暨口径达式配置）
     * @return 结果
     */
    @Override
    public int insertImcFundOrderExpression(FundOrderForm fundOrderForm) {
        List<FundOrderExpressionForm> expressionList = fundOrderForm.getFundOrderExpressionList();
        Long fundId = fundOrderForm.getFundId();
        ArrayList<ImcFundOrderExpression> expressions = new ArrayList<>();
        for (FundOrderExpressionForm fundOrderExpressionForm : expressionList) {
            ImcFundOrderExpression imcFundOrderExpression = new ImcFundOrderExpression();
            BeanUtils.copyProperties(fundOrderExpressionForm,imcFundOrderExpression);
            String variableName = fundOrderExpressionForm.getVariableName();
            QueryWrapper<ImcFundOrderVariable> wrapper = new QueryWrapper<>();
            wrapper.eq("variable_name",variableName);
            ImcFundOrderVariable variable = fundOrderVariableMapper.selectOne(wrapper);
            imcFundOrderExpression.setOrderVariableId(variable.getId());
            imcFundOrderExpression.setFundId(fundId);
            imcFundOrderExpression.setOrderStrategy(fundOrderExpressionForm.getStrategyCode());
            imcFundOrderExpression.setCreateId(SecurityUtils.getUsername());
            imcFundOrderExpression.setUpdateId(SecurityUtils.getUsername());
            imcFundOrderExpression.setCreateTime(DateUtils.getNowDate());
            imcFundOrderExpression.setUpdateTime(DateUtils.getNowDate());
            imcFundOrderExpression.setTenantId(SecurityUtils.getTenantId());
            imcFundOrderExpression.setIsDeleted(IsDeletedEnum.N.getCode());
            expressions.add(imcFundOrderExpression);
        }
        return imcFundOrderExpressionMapper.insertImcFundOrderExpressionList(expressions);
    }

    /**
     * 修改保单口径（暨口径达式配置）
     *
     * @param fundOrderForm 保单口径（暨口径达式配置）
     * @return 结果
     */
    @Override
    public int updateImcFundOrderExpression(FundOrderForm fundOrderForm) {
        //删除旧保单查询口径
        this.deleteImcFundOrderExpressionByIds(fundOrderForm);
        //新增新保单查询口径
        return insertImcFundOrderExpression(fundOrderForm);
    }

    /**
     * 批量删除保单口径（暨口径达式配置）
     *
     * @param fundOrderForm 需要删除的保单口径（暨口径达式配置）ID
     * @return 结果
     */
    @Override
    public int deleteImcFundOrderExpressionByIds(FundOrderForm fundOrderForm) {
        int update =0;
        Long fundId = fundOrderForm.getFundId();
        List<FundOrderExpressionForm> fundOrderExpressionList = fundOrderForm.getFundOrderExpressionList();
        for (FundOrderExpressionForm fundOrderExpressionForm : fundOrderExpressionList) {
            ImcFundOrderExpression imcFundOrderExpression = new ImcFundOrderExpression();
            imcFundOrderExpression.setIsDeleted(IsDeletedEnum.Y.getCode());

            UpdateWrapper<ImcFundOrderExpression> wrapper = new UpdateWrapper<>();
            wrapper.eq("fund_id",fundId);
            wrapper.eq("policy_year_flag",fundOrderExpressionForm.getPolicyYearFlag());
            update = imcFundOrderExpressionMapper.update(imcFundOrderExpression, wrapper);
        }
        return update;
    }

    /**
     * 删除保单口径（暨口径达式配置）信息
     *
     * @param id 保单口径（暨口径达式配置）ID
     * @return 结果
     */
    @Override
    public int deleteImcFundOrderExpressionById(String id) {
        return imcFundOrderExpressionMapper.deleteImcFundOrderExpressionById(id);
    }

    @Override
    public List<FundOrderExpressionVo> selectImcFundOrderExpressionByFundId(Long fundId,String policyYearFlag) {
        ImcFundOrderExpression imcFundOrderExpression = new ImcFundOrderExpression();
        imcFundOrderExpression.setFundId(fundId);
        imcFundOrderExpression.setIsDeleted("0");
        imcFundOrderExpression.setTenantId(SecurityUtils.getTenantId());
        imcFundOrderExpression.setPolicyYearFlag(policyYearFlag);
        List<ImcFundOrderExpression> fundOrderExpressions = imcFundOrderExpressionMapper.selectImcFundOrderExpressionList(imcFundOrderExpression);
        ArrayList<FundOrderExpressionVo> expressionVos = new ArrayList<>();
        for (ImcFundOrderExpression fundOrderExpression : fundOrderExpressions) {
            FundOrderExpressionVo fundOrderExpressionVo = new FundOrderExpressionVo();
            BeanUtils.copyProperties(fundOrderExpression,fundOrderExpressionVo);
            ImcFundOrderVariable fundOrderVariable = fundOrderVariableMapper.selectById(fundOrderExpression.getOrderVariableId());
            fundOrderExpressionVo.setVariableName(fundOrderVariable.getVariableName());
            fundOrderExpressionVo.setStrategyCode(fundOrderExpression.getOrderStrategy());
            expressionVos.add(fundOrderExpressionVo);
        }
        return expressionVos;
    }

    /**
     * 校验人员口径表达式
     * @param fundOrderForm
     * @return
     */
    @Override
    @Transactional
    public AjaxResult checkExpenseExpression(FundOrderForm fundOrderForm) {
        StringBuilder sqlStr = new StringBuilder();
        StringBuilder tagStr = new StringBuilder();
        ContractExpenseExpressionMessageVo messageVo = new ContractExpenseExpressionMessageVo();

        // 转换
        for (FundOrderExpressionForm item : fundOrderForm.getFundOrderExpressionList()) {

            // 协议口径变量（如果遇到括弧则直接跳过转换，避免转换成空格）
            String variableName = item.getVariableName();
            String variableLabel = item.getVariableLabel();
            if ("left_bracket".equals(variableName) || "right_bracket".equals(variableName)) {
                QueryWrapper<ImcFundOrderVariable> queryWrapper = new QueryWrapper<>();//左右括号为空,这里做下处理
                queryWrapper.eq("variable_name",variableName);
                ImcFundOrderVariable fundOrderVariable = fundOrderVariableMapper.selectOne(queryWrapper);
                sqlStr.append(fundOrderVariable.getVariableLabel());
                tagStr.append(fundOrderVariable.getVariableLabel());
            } else {
                sqlStr.append(variableName);
                tagStr.append(variableLabel);
            }


            // 运算符
            String operator = item.getOperator();
            if (StrUtil.isNotBlank(operator)) {
                sqlStr.append(" ").append(recnExpenseService.transOperator(operator, ExpenseExpressionMsgTypeEnum.SQL.name()));
                tagStr.append(" ").append(recnExpenseService.transOperator(operator, ExpenseExpressionMsgTypeEnum.TAG.name()));
            }

            // 处理策略
            String orderStrategy = item.getStrategyCode();
            if (ObjectUtil.isNotNull(orderStrategy)) {
                //code获得枚举值的value
                tagStr.append(" ").append(FundMonthlyStrategyEnum.getCode(orderStrategy));
            }

            // 协议口径变量（数值）
            String variableValue = item.getVariableValue();
            if (StrUtil.isNotBlank(variableValue)) {
                // 处理策略为“结算上月”
                if(FundMonthlyStrategyEnum.A.name().equals(orderStrategy)){
                    Date addDate = DateUtils.addMonths(new Date(), -1);
                    String yearMonth = DateUtils.parseDateToStr(DateUtils.YYYY_MM, addDate);
                    sqlStr.append(" '").append(yearMonth+"-").append(variableValue).append("'");
                    tagStr.append(" '").append(yearMonth+"-").append(variableValue).append("'");
                }else if (FundMonthlyStrategyEnum.B.name().equals(orderStrategy)) {
                    String yearMonth = DateUtils.parseDateToStr(DateUtils.YYYY_MM, new Date());
                    sqlStr.append(" '").append(yearMonth+"-").append(variableValue).append("'");
                    tagStr.append(" '").append(yearMonth+"-").append(variableValue).append("'");
                } else if(FundMonthlyStrategyEnum.C.name().equals(orderStrategy)){
                    Date addDate = DateUtils.addMonths(new Date(), 1);
                    String yearMonth = DateUtils.parseDateToStr(DateUtils.YYYY_MM, addDate);
                    sqlStr.append(" '").append(yearMonth+"-").append(variableValue).append("'");
                    tagStr.append(" '").append(yearMonth+"-").append(variableValue).append("'");
                }else{
                    sqlStr.append(" '").append(variableValue).append("'");
                    tagStr.append(" '").append(variableValue).append("'");
                }
            }

            // 逻辑运算符
            String logicalOperator = item.getLogicalOperator();
            if (StrUtil.isNotBlank(logicalOperator) && !"0".equals(logicalOperator)) {
                sqlStr.append(" ").append(recnExpenseService.transLogicalOperator(logicalOperator, ExpenseExpressionMsgTypeEnum.SQL.name())).append(" ");
                tagStr.append(" ").append(recnExpenseService.transLogicalOperator(logicalOperator, ExpenseExpressionMsgTypeEnum.TAG.name())).append(" ");
            }
        }
        log.info("基本法Id: " + fundOrderForm.getFundId());
        log.info("基本法查保单对应口径SQL： " + sqlStr.toString());
        log.info("基本法查保单对应口径TAG： " + tagStr.toString());
        messageVo.setSqlStr(sqlStr.toString());
        messageVo.setTagStr(tagStr.toString());
        log.info("messageVo： " + JSONUtil.toJsonStr(messageVo));
        try {
            this.orderRiskMapper.getOrderRiskByCriteria(sqlStr.toString());
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new BusinessException(JSONUtil.toJsonStr(messageVo));
        }
        return AjaxResult.success(messageVo);
    }
}
